package com.credithc.signature.core.server;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.credithc.baseserv.core.message.Message;
import com.credithc.baseserv.core.message.MessageFactory;
import com.credithc.baseserv.core.utils.DateTimeUtils;
import com.credithc.signature.common.constant.FddConstant;
import com.credithc.signature.common.constant.ManagerConstant;
import com.credithc.signature.common.constant.SealConstant;
import com.credithc.signature.common.mapper.FddAuthCompanyMapper;
import com.credithc.signature.common.mapper.FddAuthPersonMapper;
import com.credithc.signature.common.mapper.FddSealInfoMapper;
import com.credithc.signature.common.mapper.FddSignInfoMapper;
import com.credithc.signature.common.mapper.SealChannelMapper;
import com.credithc.signature.common.mapper.SealInfoMapper;
import com.credithc.signature.common.mapper.SignCallbackMapper;
import com.credithc.signature.common.po.FddAuthCompany;
import com.credithc.signature.common.po.FddAuthPerson;
import com.credithc.signature.common.po.FddConfig;
import com.credithc.signature.common.po.FddSealInfo;
import com.credithc.signature.common.po.FddSignInfo;
import com.credithc.signature.common.po.SealChannel;
import com.credithc.signature.common.po.SealInfo;
import com.credithc.signature.common.po.SignCallback;
import com.credithc.signature.common.ro.GetExtSignPageRo;
import com.credithc.signature.common.ro.NewSignProviderReq;
import com.credithc.signature.common.ro.core.CoreRequet;
import com.credithc.signature.common.ro.facade.FddAuthReq;
import com.credithc.signature.common.ro.facade.FddSignReq;
import com.credithc.signature.common.ro.facade.QueryAuthenticationStatusReq;
import com.credithc.signature.common.ro.manager.SealInfoRo;
import com.credithc.signature.common.ro.sign.GetExtBatchSignPageRo;
import com.credithc.signature.common.to.CallBackCompany;
import com.credithc.signature.common.to.CallBackPerson;
import com.credithc.signature.common.to.FddCompanyInfo;
import com.credithc.signature.common.to.FddPersonInfo;
import com.credithc.signature.common.to.PersonInfos;
import com.credithc.signature.common.utils.AmazonUtil3;
import com.credithc.signature.common.utils.DateUtil;
import com.credithc.signature.common.utils.FddConfigMap;
import com.credithc.signature.common.utils.ManagerBeanUtil;
import com.credithc.signature.common.utils.UUIDUtil;
import com.credithc.signature.core.constant.Constant;
import com.credithc.signature.core.service.CoreHandler;
import com.credithc.signature.core.service.UploadPDFService;
import com.credithc.signature.core.service.signprovide.fadada.FadadaProvider;
import com.credithc.signature.core.util.Base64Util;
import com.credithc.signature.core.util.FddClientUtil;
import com.credithc.signature.core.util.PathUtil;
import com.fadada.lightapi.base.ReturnBase;
import com.fadada.lightapi.beans.conformity.register.AccountRegisterRsp;
import com.fadada.lightapi.beans.conformity.verfiy.VerCompanyRsp;
import com.fadada.lightapi.beans.conformity.verfiy.VerGetUrlRsp;
import com.fadada.lightapi.beans.contract.ContractDownloadResponse;
import com.fadada.lightapi.beans.contract.ContractStatusRsp;
import com.fadada.lightapi.beans.contract.UploadContractRsp;
import com.fadada.lightapi.beans.customer.CustomerRsp;
import com.fadada.lightapi.beans.signatureOperate.SignatureOperateReq;
import com.fadada.lightapi.beans.signatureOperate.SignatureOperateRsp;
import com.fadada.lightapi.beans.witness.WitnessRsp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Decoder;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @desc: <br/>
 * @author: Jingbo Hu<br/>
 * @time：2020年07⽉13⽇<br/>
 * @version：v1.0.0<br>
 */
@Slf4j
@RestController
@RequestMapping("/api/core/v1")
public class FadadaHandler {

    @Autowired
    MessageFactory messageFactory;

    @Autowired
    FddAuthPersonMapper fddAuthPersonMapper;

    @Autowired
    FddAuthCompanyMapper fddAuthCompanyMapper;

    @Autowired
    FddSignInfoMapper fddSignInfoMapper;

    @Resource
    FddSealInfoMapper fddSealInfoMapper;

    @Autowired
    SealChannelMapper sealChannelMapper;

    @Autowired
    SignCallbackMapper signCallbackMapper;

    @Value("${signature.snapSignPdf.path}")
    private String snapSignPdf;

    @Autowired
    private FadadaProvider fadadaProvider;

    @Autowired
    private CoreHandler coreHandler;

    @Autowired
    SealInfoMapper sealInfoMapper;


    /**
     * 注册接口
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/register")
    public Message register(@RequestBody FddAuthReq req) {
        // 如果存在，查询返回
        String customerId = findRegisterData(req);
        if (StringUtils.isNotBlank(customerId)) {
            return buildRspData("1", "success", customerId);
        } else {
            // 插入数据库
            insertRegisterData(req);
            log.info("法大大【注册】请求参数： {}", req);
            AccountRegisterRsp rsp = FddClientUtil.register(req.getOpenId(), req.getAccountType(), req.getChannelNo(), req.getOpenId());
            log.info("调用法大大【注册】接口返回值： {}", rsp.toString());
            if (FddConstant.SUCCESS.equals(rsp.getCode())) {
                updateRegisterData(req, rsp);
            }
            return buildRspData(rsp.getCode(), rsp.getMsg(), rsp.getData());
        }
    }


    /**
     * 获取签章连接
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/signUrl")
    public Message getSignUrl(@RequestBody GetExtSignPageRo req) {
        log.info("法大大【获取连接】请求参数： {}", req);
        String signUrl = FddClientUtil.getSignUrl(req);
        log.info("调用法大大【获取连接】接口返回值： {}", signUrl);
        Example example = new Example(SignCallback.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("customerId", req.getCustomerId());
        criteria.andEqualTo("contractId", req.getContractId());
        SignCallback signCallback = new SignCallback();
        signCallback.setStatus(0);
        signCallback.setSignUrl(signUrl);
        signCallbackMapper.updateByExampleSelective(signCallback, example);
        return buildRspData("1", "success", signUrl);
    }



    /**
     * 获取批量签章连接
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/batch/signUrl")
    public Message getSignUrl(@RequestBody GetExtBatchSignPageRo req) {
        log.info("法大大【获取批量连接】请求参数： {}", req);
        String signUrl = FddClientUtil.getBatchSignUrl(req);
        log.info("调用法大大【获取批量连接】接口返回值： {}", signUrl);
        Example example = new Example(SignCallback.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("customerId", req.getCustomerId());
        criteria.andEqualTo("batchId", req.getBatchId());
        SignCallback signCallback = new SignCallback();
        signCallback.setStatus(0);
        signCallback.setSignUrl(signUrl);
        signCallbackMapper.updateByExampleSelective(signCallback, example);
        return buildRspData("1", "success", signUrl);
    }


    /**
     * 同步签章
     *
     * @param
     * @return
     */
    @ResponseBody
    @PostMapping("/sign/synchronous")
    public Message getSignUrl(@RequestBody CoreRequet coreRequet) throws Exception {

        String contractId = null;
        try {
            contractId = coreHandler.synchronousSign(coreRequet);
        } catch (Exception e) {
            return buildRspData("100", e.getMessage(), contractId);
        }
        return buildRspData("0", "成功", contractId);
    }

    /**
     * 获取实名认证地址
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/getAuthUrl")
    public Message getAuthUrl(@RequestBody FddAuthReq req) {
        Integer accountType = req.getAccountType();
        if (FddConstant.ACCOUNT_PSERSON.equals(accountType)) {
            FddPersonInfo personInfo = new FddPersonInfo();
            BeanUtils.copyProperties(req, personInfo);
            personInfo.setNotifyUrl(req.getCallbackUrl());
            log.info("法大大【个人实名认证】请求参数：{}", personInfo);
            VerGetUrlRsp rsp = FddClientUtil.getPersonUrl(personInfo, req.getChannelNo(), req.getCustomerId());
            log.info("法大大【个人实名认证】响应参数：{}", rsp);

            HashMap map = updateAuthUrlData(req, rsp);
            return buildRspData(rsp.getCode(), rsp.getMsg(), map);
        } else {
            FddCompanyInfo companyInfoBody = new FddCompanyInfo();
            BeanUtils.copyProperties(req, companyInfoBody);
            companyInfoBody.setNotifyUrl(req.getCallbackUrl());
            log.info("法大大【企业实名认证】请求参数：{}", companyInfoBody);
            VerGetUrlRsp rsp = FddClientUtil.getCompanyUrl(companyInfoBody, req.getChannelNo(), req.getCustomerId());
            log.info("法大大【企业实名认证】响应参数：{}", rsp);
            HashMap map = updateAuthUrlData(req, rsp);
            return buildRspData(rsp.getCode(), rsp.getMsg(), map);
        }
    }

    /**
     * 查询认证状态接口
     */
    @ResponseBody
    @PostMapping("/queryStatus")
    public Message queryStatus(@RequestBody QueryAuthenticationStatusReq req) {
        Integer accountType = req.getAccountType();
        String type = accountType == 1 ? "个人" : "企业";
        log.info("法大大【查询" + type + "认证状态】请求参数：{}", req);
        VerCompanyRsp verifyInfo = FddClientUtil.findVerifyInfo(req.getTransactionNo(), req.getAccountType(), req.getChannelNo(), req.getTransactionNo());
        try {
            if (accountType == 1) {
                CallBackPerson callBackPerson = JSONObject.parseObject(JSONObject.toJSONString(verifyInfo), CallBackPerson.class);
                completePersonInfo(callBackPerson, callBackPerson.getData().getPerson().getStatus(), "");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("法大大【查询" + type + "认证状态】响应参数：{}", verifyInfo);
        if (verifyInfo == null) {
            return buildRspData("100", "null", verifyInfo.getData());
        }
        return buildRspData(verifyInfo.getCode(), verifyInfo.getMsg(), verifyInfo.getData());
    }

    /**
     * 申请证书: 1: 编号证书 2:实名证书
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/applyCert")
    public Message applyCert(@RequestBody FddAuthReq req) {
        ReturnBase returnBase = null;
        if (req.getCertType() == 1) {
            log.info("法大大【申请编号证书】请求参数：{}", req);
            returnBase = FddClientUtil.applyNumCert(req.getCustomerId(), req.getTransactionId(), req.getChannelNo(), req.getTransactionId());
        } else {
            log.info("法大大【申请实名证书】请求参数：{}", req);
            returnBase = FddClientUtil.applyCert(req.getCustomerId(), req.getTransactionId(), req.getChannelNo(), req.getTransactionId());
        }
        log.info("法大大【申请实名证书】响应参数：{}", returnBase);
        return buildRspData(String.valueOf(returnBase.getCode()), returnBase.getMsg(), returnBase.getData());
    }

    /**
     * UUID下载图片
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/download")
    public Message download(@RequestBody FddAuthReq req) {
        log.info("法大大【UUID下载图片】请求参数：{}", req);
        String downloadUrl = FddClientUtil.downImgWithUUID(req.getUuid(), req.getChannelNo(), req.getUuid());
        log.info("法大大【UUID下载图片】响应参数：{}", downloadUrl);
        return buildRspData("1", "success", downloadUrl);
    }

    /**
     * 合同上传接口
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/uploadContract")
    public Message uploadContract(@RequestBody FddAuthReq req) {
        log.info("法大大【合同上传】请求参数：{}", req);
        UploadContractRsp rsp = FddClientUtil.uploadContract(req.getContractId(), req.getDocTitle(), req.getDocType(), req.getFile(), req.getDocUrl(), req.getValidity(), req.getChannelNo(), req.getContractId());
        log.info("法大大【合同上传】响应参数：{}", rsp);
        return buildRspData(rsp.getCode(), rsp.getMsg(), rsp.getUuid());
    }

    /**
     * 合同下载接口
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/downloadContract")
    public Message downloadContract(@RequestBody FddAuthReq req) {
        log.info("法大大【合同下载】请求参数：{}", req);
        ContractDownloadResponse rsp = FddClientUtil.contractDownload(req.getContractId(), req.getChannelNo(), req.getContractId());
        log.info("法大大【合同下载】响应参数：{}", rsp);
        return buildRspData(rsp.getCode(), rsp.getMsg(), rsp.getContent());
    }

    /**
     * 修改用户信息接口
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/modifyUserInfo")
    public Message modifyUserInfo(@RequestBody FddAuthReq req) {
        log.info("法大大【修改用户信息】请求参数：{}", req);
        CustomerRsp rsp = FddClientUtil.modifyCustomer(req.getCustomerId(), req.getMobile(), req.getEmail(), req.getChannelNo(), req.getCustomerId());
        log.info("法大大【修改用户信息】响应参数：{}", rsp);
        return buildRspData(rsp.getCode(), rsp.getMsg(), null);
    }

    /**
     * 查询用户信息接口
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/queryUserInfo")
    public Message queryUserInfo(@RequestBody FddAuthReq req) {
        log.info("法大大【查询用户信息】请求参数：{}", req);
        FddAuthPerson fddAuthPerson = fddAuthPersonMapper.selectByNoAndName(req.getCustomerIdentNo(), req.getCustomerName());
        if (fddAuthPerson == null) {
            return buildRspData("100", "该用户不存在", null);
        }
        log.info("法大大【查询用户信息】响应参数：{}", fddAuthPerson);
        //FddAuthPerson rspPersonInfo = new FddAuthPerson();
        PersonInfos personInfos = new PersonInfos();
        BeanUtils.copyProperties(fddAuthPerson, personInfos);
        return buildRspData("1", "success", personInfos);
    }

    /**
     * 合同归档
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/contractOver")
    public Message contractOver(@RequestBody FddAuthReq req) throws IOException {
        log.info("法大大【合同归档】请求参数：{}", req);
        if (req.getContractOver()) {
            WitnessRsp rsp = FddClientUtil.witness(req.getContractId(), req.getChannelNo(), req.getContractId());
            log.info("法大大【合同归档】响应参数：{}", rsp);
            String code = rsp.getCode();
            if (!code.equals("1000")) {
                return buildRspData(rsp.getCode(), rsp.getMsg(), null);
            }
            updateContractStatus(req, rsp);
            // 合同下载
            String uuid = UUIDUtil.getUUID();
            String destFileName = Constant.SNAP_PDF_PREFIX + uuid + Constant.PDF_EXT;
            String date = DateUtil.getStandardDateStr();
            String signSnapPDFPath = PathUtil.getSignSnapPDFPath(snapSignPdf, destFileName, date);
            String contractId = req.getContractId();
            FileOutputStream fileOutputStream = null;
            ContractDownloadResponse res = null;
            try {
                res = FddClientUtil.contractDownload(contractId, req.getChannelNo(), contractId);
                byte[] content = res.getContent();
                fileOutputStream = new FileOutputStream(signSnapPDFPath);
                fileOutputStream.write(content);
            } catch (IOException e) {
                log.error("法大大【合同归档】调用法大大下载合同接口发生异常......", e);
            } finally {
                fileOutputStream.close();
            }
            // 合同上传
            File file1 = new File(signSnapPDFPath);
            AmazonUtil3.uploadToS3(file1, contractId);
            // 为了节约磁盘空间，上传成功之后删除文件
            UploadPDFService.removeUploadFile(signSnapPDFPath);
            return buildRspData(rsp.getCode(), rsp.getMsg(), null);
        }
        return buildRspData("1", "success", null);
    }

    /**
     * 合同续签
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/contractRenewal")
    public Message contractRenewal(@RequestBody FddSignReq req) throws Exception {
        log.info("法大大【合同续签】请求参数：{}", req);
        // 封装请求参数
        String requestSn = UUIDUtil.getUUID();
        String contractId = req.getContractId();
        String channelNo = req.getChannelNo();
        CoreRequet coreRequet = new CoreRequet();
        coreRequet.setRequestSn(requestSn);
        coreRequet.setChannelNo(channelNo);
        coreRequet.setJsonBody(JSONObject.toJSONString(req.getJsonBody()));
        coreRequet.setSealType(req.getSealType());
        //String jsonBody = req.getJsonBody();
        List<Map<String, String>> certInfos = new ArrayList<>();
        NewSignProviderReq newSignProviderReq = req.getJsonBody();
        if (newSignProviderReq.getCertInfos() != null) {
            certInfos.addAll(newSignProviderReq.getCertInfos());
        }
        List<String> sealCodes = new ArrayList<>();
        if (newSignProviderReq.getOfficialSealsCodes() != null) {
            sealCodes.addAll(newSignProviderReq.getOfficialSealsCodes());
        }
        // 下载合同文件
        String contractPath = this.downloadContract(requestSn, contractId, req.getChannelNo());
        // 执行签章
        //String pdfPath = fadadaProvider.processSignature(coreRequet, contractPath, certInfos, sealCodes);
        // 判断是否归档
        String pdfPath = fadadaProvider.contractRenewal(req,coreRequet,contractPath);

        if (req.getContractOver()) {
            String fileId = req.getContractId();
            WitnessRsp rsp = FddClientUtil.witness(fileId, req.getChannelNo(), fileId);
            log.info("法大大【合同归档】响应参数：{}", rsp);
            FddAuthReq req1 = new FddAuthReq();
            req1.setContractId(contractId);
            req1.setChannelNo(channelNo);
            updateContractStatus(req1, rsp);
        }
        // 上传合同文件
        uploadPdfContract(contractId, requestSn, pdfPath);
        return buildRspData("1", "success", contractId);
    }

    /**
     * 查询合同状态 是否归档
     */
    @ResponseBody
    @PostMapping("/contract/status")
    public Message getContractStatus(@RequestBody FddSignReq req) throws Exception {
        log.info("法大大【查询合同状态】请求参数：{}", req);
        ContractStatusRsp contractStatus = FddClientUtil.getContractStatus(req.getContractId(), req.getChannelNo(), req.getContractId());
        log.info("法大大【合同归档】响应参数：{}", contractStatus);
        if ("1000".equals(contractStatus.getCode())) {
            return messageFactory.getInstance(Integer.valueOf(contractStatus.getContract_status()), contractStatus.getContract_status_desc());
        } else {
            return messageFactory.getInstance(Integer.valueOf(contractStatus.getCode()), contractStatus.getMsg());
        }
    }


    /**
     * 下载合同文件
     *
     * @param requestSn
     * @param contractId
     * @return
     * @throws IOException
     */
    private String downloadContract(String requestSn, String contractId, String channelNo) throws IOException {
        String date = DateUtil.getStandardDateStr();
        String signPdfName = Constant.SNAP_PDF_PREFIX + requestSn + Constant.PDF_EXT;
        String signSnapPDFPath = PathUtil.getSignSnapPDFPath(snapSignPdf, signPdfName, date);
        FileOutputStream fileOutputStream = null;
        ContractDownloadResponse res = null;
        try {
            res = FddClientUtil.contractDownload(contractId, channelNo, contractId);
            byte[] content = res.getContent();
            fileOutputStream = new FileOutputStream(signSnapPDFPath);
            fileOutputStream.write(content);
        } catch (IOException e) {
            log.error("－消息－:requestSn={},调用法大大下载合同接口发生异常......", requestSn, e);
        } finally {
            fileOutputStream.close();
        }
        return signSnapPDFPath;
    }

    /**
     * 上传合同文件到S3
     *
     * @param contractId
     * @param reqestSn
     * @param contractPath
     * @throws Exception
     */
    public void uploadPdfContract(String contractId, String reqestSn, String contractPath) throws Exception {
        File file = new File(contractPath);
        if (!file.exists()) {
            log.error("－消息－:requestSn={},文件{}不存在,上传失败", reqestSn, contractPath);
            throw new Exception("文件{" + contractPath + "}不存在");
        }
        try {
            // 上传到S3文件系统
            AmazonUtil3.uploadToS3(file, contractId);
        } catch (Exception e) {
            log.error("法大大续签接口上传合同文件发生异常......", e);
        }
    }

    /**
     * 获取文件ID
     *
     * @param filePath
     * @return
     */
    public static String getFileId(String filePath) {
        String[] snapPdf_s = filePath.split("snapPdf_");
        String snapPdf_ = snapPdf_s[1];
        return snapPdf_.split(".pdf")[0];
    }

    /**
     * 获取用户印章信息---法大大接口
     *
     * @param fddAuthReq
     * @return
     */
    @ResponseBody
    @PostMapping("/querySignatureInfo")
    public Message querySignatureInfo(@RequestBody FddAuthReq fddAuthReq) {
        log.info("法大大【获取用户印章-法大大接口】请求参数：{}", fddAuthReq);
        SignatureOperateReq req = new SignatureOperateReq();
        req.setCustomerId(fddAuthReq.getCustomerId());
        SignatureOperateRsp rsp = FddClientUtil.querySignature(req, fddAuthReq.getChannelNo(), fddAuthReq.getCustomerId());
        log.info("法大大【获取用户印章-法大大接口】响应参数：{}", rsp);
        return buildRspData(rsp.getCode(), rsp.getMsg(), rsp.getData());
    }

    /**
     * 获取印章信息---本地库查询
     *
     * @param req
     * @return
     */
    @ResponseBody
    @PostMapping("/querySealInfo")
    public Message querySealInfo(@RequestBody FddAuthReq req) {
        log.info("法大大【获取印章信息-本地库】请求参数：{}", req);
        try {
            if (req.getSealSource() == null) {
                req.setSealSource(2);
            }
            // 查询对应渠道的公章信息
            JSONArray sealInfos = null;
            if(req.getSealSource().equals(1)){
                SealInfoRo sealInfoRo = new SealInfoRo();
                sealInfoRo.setChannelNo(req.getChannelNo());
                sealInfoRo.setSealSource(req.getSealSource());
                sealInfoRo.setSealCode(req.getSealCode());
                sealInfoRo.setKeyWords(req.getKeyWords());
                sealInfoRo.setPageSize(300);
                List<SealInfo> infoList = sealInfoMapper.listByParamsAndPage(sealInfoRo);
                List<FddSealInfo> sealInfo = new ArrayList<>();
                infoList.stream().forEach(p->{
                    FddSealInfo sealInfo2 = new FddSealInfo();
                    BeanUtils.copyProperties(p,sealInfo2);
                    sealInfo.add(sealInfo2);
                });
                sealInfos = buildSealRspInfo(sealInfo);
            }else {
                List<FddSealInfo> sealInfo = fddSealInfoMapper.selectByCodeOrKeyWords(req);
                sealInfos = buildSealRspInfo(sealInfo);
            }
            return buildRspData("1", "success", sealInfos);
        } catch (Exception e) {
            log.error("法大大【获取印章信息-本地库】查询发生异常", e);
            return buildRspData("100", "fail", null);
        }
    }

    /**
     * fdd_seal_info表插入公章信息
     *
     * @param callBackCompany
     */
    @ResponseBody
    @PostMapping("/completeSealInfo")
    public String completeSealInfo(@RequestBody CallBackCompany callBackCompany) throws Exception {
        log.info("法大大【插入公章信息】请求参数：{}", callBackCompany);
        // 查询公章信息是否存在
        String sealCode = checkSealInfo(callBackCompany);
        // 查询公章渠道关联信息是否存在
        checkSealChannelInfo(callBackCompany, sealCode);
        return sealCode;
    }

    /**
     * 关联公章和渠道
     *
     * @param callBackCompany
     * @param sealCode
     */
    private void checkSealChannelInfo(CallBackCompany callBackCompany, String sealCode) throws Exception {
        String customerId = callBackCompany.getData().getCustomerId();
        FddAuthCompany fddAuthCompany = fddAuthCompanyMapper.selectByCustomerId(customerId);
        if (fddAuthCompany == null) {
            log.error("法大大【公章和渠道关联】根据customerId查询公章信息为空,customerId={}", customerId);
        }
        // 查询公章是否与渠道进行关联，否：进行关联
        String channelNo = fddAuthCompany.getChannelNo();
        SealChannel sealChannel = new SealChannel();
        sealChannel.setChannelNo(channelNo);
        sealChannel.setSealCode(sealCode);
        Map<String, Object> params = ManagerBeanUtil.buildQueryParams(sealChannel);
        List<SealChannel> sealChannels = sealChannelMapper.selectByExample(params.get(ManagerConstant.EXAMPLE));
        if (sealChannels == null || sealChannels.size() == 0) {
            saveSealChannelInfo(channelNo, sealCode);
            log.info("法大大【公章和渠道关联】成功......");
        }
    }

    /**
     * 保存公章信息
     *
     * @param callBackCompany
     * @return
     */
    private String checkSealInfo(CallBackCompany callBackCompany) throws Exception {
        // 法人信息
        CallBackCompany.DataBean.ManagerBean manager = callBackCompany.getData().getManager();
        String name = manager.getPersonName();
        String idCard = manager.getIdCard();
        String mobile = manager.getMobile();
        // 公司信息
        CallBackCompany.DataBean.CompanyBean company = callBackCompany.getData().getCompany();
        String companyName = company.getCompanyName();
        String organization = company.getOrganization();
        String customerId = callBackCompany.getData().getCustomerId();
        //获取渠道编号
        FddAuthCompany fac = fddAuthCompanyMapper.selectByCustomerId(customerId);
        if (fac == null) {
            throw new Exception("法大大【公章和渠道关联】根据customerId查询公章信息为空,customerId=" + customerId);
        }
        String channelNo = fac.getChannelNo();
        // 获取appID
        FddConfig fddConfig = FddConfigMap.getConfig().get(channelNo);
        String appId = fddConfig.getAppId();
        // 查询是公章否存在
        FddSealInfo sealInfoParams = new FddSealInfo();
        sealInfoParams.setAppId(appId);
        sealInfoParams.setIdentificationNo(organization);
        sealInfoParams.setSealSource(SealConstant.SEALSOURCE_FDD);
        Map<String, Object> params = ManagerBeanUtil.buildQueryParams(sealInfoParams);
        FddSealInfo fddSealInfo = fddSealInfoMapper.selectOneByExample(params.get(ManagerConstant.EXAMPLE));
        if (fddSealInfo != null) {
            log.info("该公章信息已存在......sealCode={},sealOrg={},sealName={},identificationNo={},keyWords={}", fddSealInfo.getSealCode(), fddSealInfo.getSealOrg(), fddSealInfo.getSealName(), fddSealInfo.getIdentificationNo(), fddSealInfo.getKeyWords());
            return fddSealInfo.getSealCode();
        }
        FddSealInfo saveInfo = new FddSealInfo();
        buildSealInfo(callBackCompany, name, idCard, mobile, companyName, organization, customerId, channelNo, appId, saveInfo);
        // 保存公章信息
        try {
            fddSealInfoMapper.insert(saveInfo);
            log.info("法大大【自动生成公章】成功......");
        } catch (Exception e) {
            log.error("法大大【自动生成公章】发生异常", e);
        }
        return saveInfo.getSealCode();
    }

    /**
     * 保存公章渠道关联信息
     *
     * @param channelNo
     * @param sealCode
     */
    private void saveSealChannelInfo(String channelNo, String sealCode) {
        SealChannel sealChannel = new SealChannel();
        sealChannel.setChannelNo(channelNo);
        sealChannel.setSealCode(sealCode);
        sealChannel.setStatus(ManagerConstant.Enable);
        sealChannelMapper.insert(sealChannel);
    }

    /**
     * 封装公章返回信息
     *
     * @param sealInfo
     * @return
     */
    private JSONArray buildSealRspInfo(List<FddSealInfo> sealInfo) {
        JSONArray array = new JSONArray();
        for (FddSealInfo info : sealInfo) {
            JSONObject object = new JSONObject();
            object.put("sealName", info.getSealName());
            object.put("sealCode", info.getSealCode());
            object.put("keyWords", info.getKeyWords());
            object.put("organization", info.getIdentificationNo());
            object.put("status", info.getStatus());
            array.add(object);
        }
        return array;
    }

    /**
     * 封装sealInfo表信息
     *
     * @param callBackCompany
     * @param name
     * @param idCard
     * @param mobile
     * @param companyName
     * @param organization
     * @param customerId
     * @param channelNo
     * @param appId
     * @param sealInfo
     * @return
     * @throws IOException
     */
    private void buildSealInfo(@RequestBody CallBackCompany callBackCompany, String name, String idCard, String mobile, String companyName, String organization, String customerId, String channelNo, String appId, FddSealInfo sealInfo) throws IOException {
        sealInfo.setSealType(ManagerConstant.SEAL_ENTERPRISE);
        sealInfo.setSealCode("OFFICE_" + UUIDUtil.getRandomFixedLengthCode(8));
        sealInfo.setSealPwd(UUIDUtil.getRandomFixedLengthCode(10));
        sealInfo.setSealPerson(SealConstant.SEAL_PERSON);
        sealInfo.setSealOrg(companyName);
        sealInfo.setSealName(companyName);
        sealInfo.setCustomerType(ManagerConstant.SEAL_ENTERPRISE);
        sealInfo.setIdentificationType(SealConstant.IDENTIFICATIONTYPE);
        sealInfo.setIdentificationNo(organization);
        sealInfo.setSealStatus(ManagerConstant.SEAL_SUCCESS);
        sealInfo.setLifePeriod(1);
        sealInfo.setSealSource(SealConstant.SEALSOURCE_FDD);
        SignatureOperateReq req = new SignatureOperateReq();
        req.setCustomerId(customerId);
        SignatureOperateRsp rsp = FddClientUtil.querySignature(req, channelNo, customerId);
        if (rsp.getCode().equals(FddConstant.SUCCESS)) {

            JSONArray parse = (JSONArray) JSONArray.parse(JSONObject.toJSONString(rsp.getData()));
            JSONObject object = (JSONObject) parse.get(0);
            String imgBase64 = (String) object.get("signature_img_base64");
            String signatureId = (String) object.get("signature_id");
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] data = decoder.decodeBuffer(imgBase64);
            sealInfo.setImage(data);
            sealInfo.setExt1(signatureId);
            FddAuthCompany fddAuthCompany = new FddAuthCompany();
            fddAuthCompany.setSignatureId(signatureId);
            fddAuthCompany.setUpdateTime(new Date());
            Example example = new Example(FddAuthCompany.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("customerId", customerId);
            fddAuthCompanyMapper.updateByExampleSelective(fddAuthCompany, example);
        }
        if (callBackCompany != null) {
            String keyName = companyName.substring(0, 4);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < 4; i++) {
                builder.append("_").append(keyName.charAt(i));
            }
            builder.append("_");
            sealInfo.setKeyWords(builder.toString());
        }
        sealInfo.setAppId(appId);
        sealInfo.setStatus(ManagerConstant.Enable);
        sealInfo.setOfficeSealType(1);
        sealInfo.setUseType(1);
        sealInfo.setCreateTime(new Date());
        sealInfo.setUpdateTime(new Date());
        sealInfo.setLegalPersonId(idCard);
        sealInfo.setLegalPersonName(name);
        sealInfo.setLegalPersonCardType("0");
        sealInfo.setPhone(mobile);
        sealInfo.setContactPhone(mobile);
    }

    /**
     * 补全个人用户信息
     *
     * @param callBackPerson
     * @return
     */
    @ResponseBody
    @PostMapping("/completePersonInfo")
    public void completePersonInfo(@RequestBody CallBackPerson callBackPerson, @RequestParam("status") String status, @RequestParam("statusDesc") String statusDesc) throws ParseException {
        log.info("法大大【补全个人用户信息】请求参数：{}", callBackPerson);
        CallBackPerson.DataBean.PersonBean person = callBackPerson.getData().getPerson();
        String headPhotoPath = person.getHeadPhotoPath();
        String auditorTime = person.getAuditorTime();
        String passTime = callBackPerson.getData().getPassTime();
        String authenticationSubmitTime = callBackPerson.getData().getAuthenticationSubmitTime();
        String transactionNo = callBackPerson.getData().getTransactionNo();
        // 封装参数
        FddAuthPerson fddAuthPerson = new FddAuthPerson();
        fddAuthPerson.setIdentFrontPath(headPhotoPath);
        fddAuthPerson.setStatus(status);
        fddAuthPerson.setCustomerName(person.getPersonName());
        fddAuthPerson.setStatusDesc(statusDesc);
        if (StringUtils.isNotBlank(auditorTime)) {
            fddAuthPerson.setAuditorTime(DateTimeUtils.strToDate(auditorTime));
        }
        if (StringUtils.isNotBlank(passTime)) {
            fddAuthPerson.setPassTime(DateTimeUtils.strToDate(passTime));
        }
        if (StringUtils.isNotBlank(authenticationSubmitTime)) {
            fddAuthPerson.setAuthSubmitTime(DateTimeUtils.strToDate(authenticationSubmitTime));
        }
        fddAuthPerson.setUpdateTime(new Date());
        fddAuthPerson.setCustomerIdentNo(person.getIdCard());
        fddAuthPerson.setCustomerIdentType(person.getType());
        Example example = new Example(FddAuthPerson.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("transactionId", transactionNo);
        fddAuthPersonMapper.updateByExampleSelective(fddAuthPerson, example);
    }

    /**
     * 补全企业用户信息
     *
     * @param callBackCompany
     * @return
     */
    @ResponseBody
    @PostMapping("/completeCompanyInfo")
    public void completeCompanyInfo(@RequestBody CallBackCompany callBackCompany, @RequestParam("status") String status, @RequestParam("statusDesc") String statusDesc) throws ParseException {
        log.info("法大大【补全企业用户信息】请求参数：{}", callBackCompany);
        CallBackCompany.DataBean.ManagerBean manager = callBackCompany.getData().getManager();
        String name = manager.getPersonName();
        String idCard = manager.getIdCard();
        String mobile = manager.getMobile();
        String headPhotoPath = manager.getHeadPhotoPath();
        String personAuditorTime = manager.getAuditorTime();

        CallBackCompany.DataBean.CompanyBean company = callBackCompany.getData().getCompany();
        String companyName = company.getCompanyName();
        // 是否有代理人，1：代理人，0：法人
        String hasagent = company.getHasagent();
        String organization = company.getOrganization();
        String organizationPath = company.getOrganizationPath();
        String relatedTransactionNo = company.getRelatedTransactionNo();
        String companyAuditorTime = company.getAuditorTime();
        String passTime = callBackCompany.getData().getPassTime();
        String authenticationSubmitTime = callBackCompany.getData().getAuthenticationSubmitTime();
        String transactionNo = callBackCompany.getData().getTransactionNo();
        // 封装参数
        FddAuthCompany fddAuthCompany = new FddAuthCompany();
        fddAuthCompany.setStatus(status);
        fddAuthCompany.setStatusDesc(statusDesc);
        fddAuthCompany.setPersonName(name);
        fddAuthCompany.setPersonId(idCard);
        fddAuthCompany.setPersonMobile(mobile);
        fddAuthCompany.setPersonIdFrontPath(headPhotoPath);
        fddAuthCompany.setCompanyPrincipalType(hasagent);
        fddAuthCompany.setCompanyName(companyName);
        fddAuthCompany.setOrganization(organization);
        fddAuthCompany.setOrganizationPath(organizationPath);
        fddAuthCompany.setVerifiedSerialNo(relatedTransactionNo);
        if (StringUtils.isNotBlank(passTime)) {
            fddAuthCompany.setPassTime(DateTimeUtils.strToDate(passTime));
        }
        if (StringUtils.isNotBlank(personAuditorTime)) {
            fddAuthCompany.setPersonAuditorTime(DateTimeUtils.strToDate(personAuditorTime));
        }
        if (StringUtils.isNotBlank(companyAuditorTime)) {
            fddAuthCompany.setCompanyAuditorTime(DateTimeUtils.strToDate(companyAuditorTime));
        }
        if (StringUtils.isNotBlank(authenticationSubmitTime)) {
            fddAuthCompany.setAuthSubmitTime(DateTimeUtils.strToDate(authenticationSubmitTime));
        }
        fddAuthCompany.setUpdateTime(new Date());
        Example example = new Example(FddAuthCompany.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("transactionId", transactionNo);
        fddAuthCompanyMapper.updateByExampleSelective(fddAuthCompany, example);
    }

    /**
     * 更新合同状态
     *
     * @param req
     * @param rsp
     */
    private void updateContractStatus(FddAuthReq req, WitnessRsp rsp) {
        String code = rsp.getCode();
        if (code.equals(FddConstant.CONTRACT_SUCCESS)) {
            String channelNo = req.getChannelNo();
            String contractId = req.getContractId();
            FddSignInfo fddSignInfo = new FddSignInfo();
            fddSignInfo.setContractStatus(1);
            fddSignInfo.setChannelNo(channelNo);
            fddSignInfo.setContractId(contractId);
            fddSignInfo.setUpdateTime(new Date());
            fddSignInfoMapper.updateByNoAndId(fddSignInfo);
        }
    }

    /**
     * 根据openid查询数据
     *
     * @param req
     * @return
     */
    private String findRegisterData(FddAuthReq req) {
        Integer accountType = req.getAccountType();
        if (FddConstant.ACCOUNT_PSERSON.equals(accountType)) {
            FddAuthPerson fddAuthPerson = new FddAuthPerson();
            fddAuthPerson.setOpenId(req.getOpenId());
            FddAuthPerson fddAuthPerson1 = fddAuthPersonMapper.selectOne(fddAuthPerson);
            if (fddAuthPerson1 != null) {
                return fddAuthPerson1.getCustomerId();
            }
        } else {
            FddAuthCompany fddAuthCompany = new FddAuthCompany();
            fddAuthCompany.setOpenId(req.getOpenId());
            FddAuthCompany fddAuthCompany1 = fddAuthCompanyMapper.selectOne(fddAuthCompany);
            if (fddAuthCompany1 != null) {
                return fddAuthCompany1.getCustomerId();
            }
        }
        return null;
    }

    /**
     * 保存数据
     *
     * @param req
     */
    private void insertRegisterData(FddAuthReq req) {
        Integer accountType = req.getAccountType();
        if (FddConstant.ACCOUNT_PSERSON.equals(accountType)) {
            FddAuthPerson fddAuthPerson = new FddAuthPerson();
            BeanUtils.copyProperties(req, fddAuthPerson);
            fddAuthPerson.setCreateTime(new Date());
            fddAuthPersonMapper.insertSelective(fddAuthPerson);
        } else {
            FddAuthCompany fddAuthCompany = new FddAuthCompany();
            BeanUtils.copyProperties(req, fddAuthCompany);
            fddAuthCompany.setCreateTime(new Date());
            fddAuthCompanyMapper.insert(fddAuthCompany);
        }
    }

    /**
     * 更新注册返回OpenID
     *
     * @param req
     * @param rsp
     */
    private void updateRegisterData(FddAuthReq req, AccountRegisterRsp rsp) {
        Integer accountType = req.getAccountType();
        String customerId = (String) rsp.getData();
        String openId = req.getOpenId();
        if (FddConstant.ACCOUNT_PSERSON.equals(accountType)) {
            FddAuthPerson fddAuthPerson = new FddAuthPerson();
            fddAuthPerson.setCustomerId(customerId);
            fddAuthPerson.setUpdateTime(new Date());
            Example example = new Example(FddAuthPerson.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("openId", openId);
            fddAuthPersonMapper.updateByExampleSelective(fddAuthPerson, example);
        } else {
            FddAuthCompany fddAuthCompany = new FddAuthCompany();
            fddAuthCompany.setCustomerId(customerId);
            fddAuthCompany.setUpdateTime(new Date());
            Example example = new Example(FddAuthCompany.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("openId", openId);
            fddAuthCompanyMapper.updateByExampleSelective(fddAuthCompany, example);
        }
    }

    /**
     * 更新获取认证地址返回信息
     *
     * @param req
     * @param rsp
     * @return
     */
    private HashMap updateAuthUrlData(FddAuthReq req, VerGetUrlRsp rsp) {
        Integer accountType = req.getAccountType();
        String customerId = req.getCustomerId();
        JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(rsp.getData()));
        String transactionNo = (String) object.get("transactionNo");
        String url = (String) object.get("url");
        String newUrl = Base64Util.decode(url);
        HashMap map = new HashMap();
        map.put("url", newUrl);
        map.put("customerId", customerId);
        map.put("transactionNo", transactionNo);
        if (FddConstant.ACCOUNT_PSERSON.equals(accountType)) {
            FddAuthPerson fddAuthPerson = new FddAuthPerson();
            fddAuthPerson.setTransactionId(transactionNo);
            fddAuthPerson.setAuthUrl(newUrl);
            fddAuthPerson.setUpdateTime(new Date());
            Example example = new Example(FddAuthPerson.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("customerId", req.getCustomerId());
            fddAuthPersonMapper.updateByExampleSelective(fddAuthPerson, example);
            log.info("调用法大大【获取个人实名认证地址】接口返回值 : {}", newUrl);
        } else {
            FddAuthCompany fddAuthCompany = new FddAuthCompany();
            fddAuthCompany.setTransactionId(transactionNo);
            fddAuthCompany.setAuthUrl(newUrl);
            fddAuthCompany.setUpdateTime(new Date());
            Example example = new Example(FddAuthCompany.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("customerId", req.getCustomerId());
            fddAuthCompanyMapper.updateByExampleSelective(fddAuthCompany, example);
            log.info("调用法大大【获取企业实名认证地址】接口返回值 : {}", newUrl);
        }
        return map;
    }

    /**
     * 封装返回值
     *
     * @param code
     * @param msg
     * @param data
     * @return
     */
    private Message buildRspData(String code, String msg, Object data) {
        Integer codeVal = Integer.valueOf(code);
        if (StringUtils.isNotBlank(msg) && data == null) {
            return messageFactory.getInstance(codeVal, msg);
        } else if (StringUtils.isNotBlank(msg) && data != null) {
            return messageFactory.getInstance(codeVal, msg, data);
        }
        return messageFactory.getInstance(codeVal);
    }
}
